var fs = require('fs');
var config = require('./config.json');
var EventProxy = require('eventproxy');
var zip = require('./common/zip.js');
var path = require('path');
var _ = require('lodash');
var logger = require('log4js').getLogger();
var request = require('request');
var waterfall = require('async-waterfall');
var removeDir = require('./common/removeDir.js');

var decompress = require('decompress');
var decompressUnzip = require('decompress-unzip');

var uuid = require('uuid');
var platform = require('os').platform();
var child_process = require('child_process');
var execSync = child_process.execSync;
var getTargetDirs = require('./dirs.js').getTargetDirs;
var workspace_dirs = require('./dirs.js').workspace_dirs;
var fireWorkspaceUpdate = require('./notify.js').fireWorkspaceUpdate;
var notifyEnzyme = require('./notify.js').notifyEnzyme;
var compress_suffix_zip = ".zip";
var sdp_config = require('./sdp_config.json');
var local_repos = config.local_repo_addr;
var downloadGoods = require('./local_repo.js').downloadGoods;

var copyTarget = function (workspace, call_back) {
    var work_name = workspace.work_name;
    var namespace = workspace.namespace;
    var project_name = workspace.project_name;
    var project_dependencies = workspace.project_dependencies;
    var root = config.workspace.workspeces_path;
    var target_root = path.join(root, namespace, project_name, work_name, workspace_dirs.Target);
    var temp_Path = path.join(root, namespace, project_name, work_name, workspace_dirs.goods_temp);

    fs.exists(temp_Path, function (exists) {
        if (exists) {
            removeDir.remove(temp_Path, function (err) {//删除旧的依赖
                if (err) {
                    logger.info("删除残留goods失败");
                    return call_back(err);
                }
                logger.info("删除残留goods成功");
            });
        }
        fs.mkdir(temp_Path, function (err) {
            if (err) {
                return call_back(err);
            }
            logger.info("创建target目录成功");
            //ProjectProxy.getProjectById(project_id, function (err, project) {
            //    if (err) {
            //        return call_back(err);
            //    }
            var dependencies = project_dependencies;
            _.remove(dependencies, function (n) {
                return n.status <= 1;
            })
            var fileArray = [];
            var epp = new EventProxy();
            epp.after('push_file', dependencies.length, function () {
                //从本地仓库拷最新商品到临时文件夹
                copyList(temp_Path, fileArray, function (err) {
                    if (err) {
                        return call_back(err);
                    }
                    logger.info("拷最新商品到临时文件成功");
                    var dirs = getTargetDirs();
                    //删除旧的依赖
                    removeDir.remove(target_root, function (err) {
                        if (err) {
                            return call_back(err);
                        }
                        var epm = new EventProxy();
                        epm.after('mkdir_target', dirs.length, function () {
                            logger.info("删除旧依赖，创建新依赖成功");
                            call_back();
                        });
                        //创建新的依赖文件夹
                        dirs.map(function (dir, i) {
                            fs.mkdirSync(path.join(root, namespace, project_name, work_name, dir));
                            epm.emit('mkdir_target');
                        });
                    });
                })
            });
            dependencies.map(function (dependency, i) {
                if (dependency.type == sdp_config.goods_type.core_java) {
                    fileArray.push(dependency.name + "_" +
                        dependency.goods_version +
                        compress_suffix_zip);
                } else {
                    fileArray.push(dependency.name + "_" +
                        dependency.goods_version +
                        compress_suffix_zip);
                }
                epp.emit('push_file');
            });
            //});
        });
    });
}

exports.copyTarget = copyTarget;

/**
 * 解压的全部是mk商品，mk商品里包含好多压缩的mk产品
 * @param dependencies
 * @param work_name
 * @param call_back
 */
var unzip_target = function (dependencies, work_name, call_back) {
    var copydepen = [];
    dependencies.map(function (depen, i) {
        copydepen.push(depen);
    });
    var mk_dependencies = _.remove(copydepen, function (n) {
        return n.type == sdp_config.goods_type.MK && n.status > 1;
    });
    var full_name = "workspace" + work_name;
    var ep = new EventProxy();
    ep.fail(call_back);
    ep.after('unzip_target', mk_dependencies.length, function (errList) {
        _.remove(errList, function (n) {
            return typeof (n) == "undefined";
        })
        if (errList.length > 0) {
            call_back(errList);
        } else {
            call_back(null);
        }
    });
    mk_dependencies.map(function (dependency, i) {
        var goods_path = path.join(config.workspace.workspeces_path, full_name,
            workspace_dirs.goods_temp, dependency.name + "_" +
            dependency.goods_version + compress_suffix_zip);
        var dir_path = path.join(config.workspace.workspeces_path, full_name,
            workspace_dirs.goods_temp, dependency.name);
        fs.exists(dir_path, function (exists) {
            if (!exists) {
                fs.mkdir(dir_path, function (err) {
                    if (err) {
                        call_back(err);
                        return;
                    }
                    decompress(goods_path, dir_path, {
                        plugins: [
                            decompressUnzip()
                        ]
                    }).then(function (data) {
                        if (data.length == 0) {
                            ep.emit("unzip_target", "解压文件出错");
                        } else {
                            ep.emit("unzip_target");
                        }
                    });
                });
            }
        });
    });
}

/**
 * 商品直接按分类解压到目标文件
 * @param dependencies
 * @param work_name
 * @param call_back
 */
var distributeDepen = function (workspace, call_back) {
    var full_name = "workspace" + work_name;
    var target_path = "";
    var dependencies = workspace.project_dependencies;
    var work_name = workspace.work_name;
    var namespace = workspace.namespace;
    var project_name = workspace.project_name;
    _.remove(dependencies, function (n) {
        return n.status <= 1;
    })

    var epd = new EventProxy();
    epd.after('distribute_depen', dependencies.length, function (errList) {
        _.remove(errList, function (n) {
            return typeof (n) == "undefined";
        })
        if (errList.length > 0) {
            call_back(errList);
        }
        call_back(null);
    });
    dependencies.map(function (dependency, i) {
        //mk商品是多个mk产品集合，读取临时解压目录，然后再逐个解压
        if (dependency.type == sdp_config.goods_type.MK || dependency.type == 'app_plugin') {
            var dir_path = path.join(config.workspace.workspeces_path,
                namespace,project_name,work_name, workspace_dirs.goods_temp, dependency.name);
            fs.readdir(dir_path, function (err, array) {
                if (err) {
                    return call_back(err);
                }
                var epc = new EventProxy();
                epc.after('copy_depen', array.length, function (errList) {
                    var err = _.remove(errList, function (n) {
                        return typeof (n) == "undefined";
                    })
                    if (errList.length > 0) {
                        call_back(errList);
                    }
                    epd.emit('distribute_depen');
                });
                array.map(function (filename, i) {
                    //解压文件
                    decompress(path.join(dir_path, filename), path.join(config.workspace.workspeces_path,
                        full_name, workspace_dirs.Target), {
                        plugins: [
                            decompressUnzip()
                        ]
                    }).then(function (data) {
                        if (data.length == 0) {
                            return call_back("解压文件出错");
                        } else {
                            epc.emit('copy_depen');
                        }
                    });
                });
            });
        } else {
            //core_java和core_node商品直接解压
            var dir_path = path.join(config.workspace.workspeces_path,
                namespace,project_name,work_name, workspace_dirs.goods_temp);

            if (dependency.type == sdp_config.goods_type.core_java) {
                target_path = path.join(workspace_dirs.Target,
                    workspace_dirs.Core, workspace_dirs.Core_Java);
            } else if (dependency.type == sdp_config.goods_type.core_node) {
                target_path = path.join(workspace_dirs.Target,
                    workspace_dirs.Core, workspace_dirs.Core_Node);
            }
            var source_path = path.join(dir_path, dependency.name + "_" +
                dependency.goods_version + compress_suffix_zip);
            //解压文件
            decompress(source_path, path.join(config.workspace.workspeces_path,
                namespace,project_name,work_name, target_path), {
                plugins: [
                    decompressUnzip()
                ]
            }).then(function (data) {
                if (data.length == 0) {
                    return call_back("解压文件出错");
                } else {
                    epd.emit('distribute_depen');
                }
            });
        }
    });
}

var linkTarget = function (workspace, isWin, callback) {
    var work_name = workspace.work_name;
    var namespace = workspace.namespace;
    var project_name = workspace.project_name;
    var project_dependencies = workspace.project_dependencies;
    var workspaces = config.workspace.workspeces_path;
    var target_root;
    var repo_path = config.local_repo_addr;

    try {
        fs.accessSync(repo_path, fs.R_OK);
    } catch (e) {
        fs.mkdirSync(repo_path);
    }
    target_root = path.join(workspaces, namespace, project_name, work_name, workspace_dirs.Target);
    var dependencies = project_dependencies;
    _.remove(dependencies, function (n) {  //只对正常状态和有更新状态的依赖进行操作
        return n.status < 1;
    });
    var fileArray = [];
    var nectar_plugins = [];
    var need_download = [];
    var ep = new EventProxy();
    ep.fail(callback);
    dependencies.map(function(dep){
        if(dep.status == 1){
            need_download.push(dep);
        }
    });
    if(need_download.length){
        need_download.map(function(de){
            downloadGoods(de.goods_version, de.name, de.type, function (err, data) {
                if (err) {
                    return ep.throw(err);
                }

                ep.emit("download");
            });
        });
        ep.after("download",need_download.length,function(){
            ep.emit('goods_download');
        })

    };
    ep.on("goods_download",function(){
        ep.after('push_file', dependencies.length, function () {
            fileArray.map(function (dependency) {
                var dirs = [];
                var core_java = sdp_config.goods_type.core_java;
                var core_node = sdp_config.goods_type.core_node;
                var mk = sdp_config.goods_type.MK;
                var nectar_plugin = "app_plugin";
                switch (dependency.type) {
                    case core_java:
                        dirs.push({
                            src_path: path.join(repo_path, dependency.file_name, "bundles"),
                            target_path: path.join(target_root, "core", "java", "bundles")
                        });
                        break;
                    case core_node:
                        dirs.push({
                            src_path: path.join(repo_path, dependency.file_name),
                            target_path: path.join(target_root, "core", "node")
                        });
                        break;
                    case mk:
                        dirs.push({
                            src_path: path.join(repo_path, dependency.file_name, "backend", "dev"),
                            target_path: path.join(target_root, "backend", "dev")
                        });
                        dirs.push({
                            src_path: path.join(repo_path, dependency.file_name, "backend", "prod"),
                            target_path: path.join(target_root, "backend", "prod")
                        });
                        dirs.push({
                            src_path: path.join(repo_path, dependency.file_name, "products"),
                            target_path: path.join(target_root, "products")
                        });
                        break;
                    case nectar_plugin:
                        dirs.push({
                            src_path: path.join(repo_path, dependency.file_name),
                            target_path: path.join(target_root, "nectar_plugin")
                        });
                        break;
                }

                dirs.map(function (dir) {
                    var file_array = fs.readdirSync(dir.src_path);
                    file_array.map(function (filename, i) {
                        //创建符号链接

                        var src = path.join(dir.src_path, filename);
                        var target = path.join(dir.target_path, filename);
                        fs.exists(target, function (exists) {
                            if (exists) {
                                logger.error("make symbolic link failed :" + target + " has existed!");
                                return callback("make symbolic link failed :" + target + " has existed!");
                            }
                        });
                        fs.exists(src, function (exists) {
                            if (exists) {
                                var stat = fs.statSync(src);
                                var cmdStr;
                                if (isWin) {
                                    if (stat.isDirectory()) {
                                        cmdStr = 'mklink /j ' + target + ' ' + src;
                                    } else {
                                        cmdStr = 'mklink ' + target + ' ' + src;
                                    }
                                    execSync(cmdStr);
                                }
                                else {
                                    cmdStr = 'ln -sfT ' + src + ' ' + target;
                                    execSync(cmdStr);
                                }
                            } else {
                                logger.error("make symbolic link for '" + src + "'failed: no such file!");
                                return callback("make symbolic link for '" + src + "'failed: no such file!");
                            }
                        });

                    });
                    logger.info('linking ' + dir.src_path + ' to ' + dir.target_path + ' completed!');
                });
            });
            logger.info("create plugin.json for app_plugins");
            var package_obj = {};
            package_obj.RN_plugins = nectar_plugins;
            var package_str = JSON.stringify(package_obj);
            fs.writeFile(path.join(target_root, "nectar_plugin", 'plugin.json'), package_str, 'utf-8', function (err) {
                if (err) {
                    return callback("create plugin.json for app_plugins error!");
                } else {
                    callback(null);
                }
            });
        });
        //删除旧的依赖
        fs.exists(target_root, function (exists) {
            var target_dirs = getTargetDirs();
            ep.after('mkdir_target', target_dirs.length, function () {
                dependencies.map(function (dependency) {
                    fileArray.push({
                        file_name: dependency.name + "_" +
                        dependency.goods_version, type: dependency.type
                    });
                    ep.emit('push_file');
                });
            });
            if (exists) {
                removeDir.remove(target_root, function (err) {
                    if (err) {
                        return callback(err);
                    }
                    try {
                        target_dirs.map(function (dir) {
                            fs.mkdirSync(path.join(workspaces, namespace, project_name, work_name, dir));
                            ep.emit('mkdir_target');
                        });
                    } catch (e) {
                        return callback(e);
                    }

                });
            } else {
                try {
                    target_dirs.map(function (dir) {
                        fs.mkdirSync(path.join(workspaces, namespace, project_name, work_name, dir));
                        ep.emit('mkdir_target');
                    });
                } catch (e) {
                    return callback(e);
                }
            }

        });
    });

}
exports.linkTarget = linkTarget;
/**
 * 更新工作空间依赖
 * {workspace_id:工作空间id}
 * @param req
 * @param res
 * @param next
 */
exports.downloadTarget = function (req, res, next) {
    res.setHeader("Access-Control-Allow-Origin", "*");//跨域请求时需要
    var work_id = req.body.work_id;
    switch (platform) {
        case 'linux' :
        case 'darwin' :
            link(work_id, false, function (err) {
                if (err) {
                    logger.error(err);
                    res.format_json({}, 500);
                } else {
                    res.format_json({}, 200);
                }
            });
            break;
        case 'win32' :
            link(work_id, true, function (err) {
                if (err) {
                    logger.error(err);
                    res.format_json({}, 500);
                } else {
                    res.format_json({}, 200);
                }
            });
            break;
        default :
            copy(work_id, function (err) {
                if (err) {
                    logger.error(err);
                    res.format_json({}, 500);
                } else {
                    res.format_json({}, 200);
                }
            })
    }

};
exports.copy = function (workspace, isWin, call_back) {
    var work_name = workspace.work_name;
    var namespace = workspace.namespace;
    var project_name = workspace.project_name;
    var project_dependencies = workspace.project_dependencies;
    var root = config.workspace.workspeces_path;
    waterfall([
        //1.获取工作空间
        //2.拷贝商品
        function (cb) {
            copyTarget(workspace, function (err, data) {
                if (err) {
                    logger.error("拷贝商品失败");
                    return call_back(err);
                }
                logger.info("拷贝商品成功");
                cb(null);
            });
        },
        //3.解压商品
        function (cb) {
            unzip_target(project_dependencies, work_name, function (err) {
                if (err) {
                    logger.error("解压商品失败");
                    return call_back(err);
                }
                logger.info("解压商品成功");
                cb(null);
            });
        },
        //4.分发商品到指定目录
        function (cb) {
            distributeDepen(workspace, function (err) {
                if (err) {
                    logger.error("分发所有商品失败");
                    return call_back(err);
                }
                logger.info("分发所有商品成功");
                cb(null);
            });
        },
        //5.删除临时文件
        function (cb) {
            removeDir.remove(path.join(root, "workspace" + workspace.work_name,
                workspace_dirs.goods_temp), function (err) {
                if (err) {
                    logger.error("删除临时文件失败");
                    return call_back(err);
                }
                logger.info("删除临时文件成功");
                cb(null);
            });
        }

    ], function (err, result) {
        if (err) {
            logger.error(err);
            return call_back("未知的异常，工作空间依赖更新失败");
        }
        call_back(null, "done");
    });
};


//通过创建符号链接的形式更新target

var link = function (data, isWin, call_back) {
    linkTarget(data, isWin, function (err, data) {
        if (err) {
            logger.error("创建符号链接失败");
            return call_back({msg: "创建符号链接失败", error: err});
        }
        logger.info("依赖创建成功");
        call_back(null,{msg: "依赖创建成功"});
    });
};
exports.link = link;
var CountDown = function (count, callback) {
    this.down = function () {
        if (!--count) callback(null, {
            successNum: successNum,
            errs: errs
        });
    }
    var successNum = 0;
    this.addSuccessNum = function () {
        successNum++;
    }
    var errs = [];
    this.addErrs = function (err) {
        errs.push(err);
    }
}
var copyList = function (tar_fullPath, fileNames, call_back) {
    if (null != tar_fullPath && null != fileNames && fileNames.length > 0) {
        var countDown = new CountDown(fileNames.length, function (err, data) {
            exe_callback(err, data, call_back);
        });
        for (var i = 0; i < fileNames.length; i++) {
            copyFile({
                tar_fullPath: tar_fullPath,
                fileName: fileNames[i]
            }, function (err, data) {
                if (err) {
                    countDown.addErrs(err);
                } else {
                    countDown.addSuccessNum();
                }
                countDown.down();
            });
        }
    } else {
        exe_callback("参数不全，无法拷贝", null, call_back);
    }
}

function copyFile(param, callback) {
    if (null == param.fileName || param.fileName.trim().length == 0) {
        exe_callback("参数fileName为空，拷贝失败", null, callback);
    } else if (null == param.tar_fullPath || param.tar_fullPath.trim().length == 0) {
        exe_callback("参数tar_fullPath为空，拷贝失败", null, callback);
    } else {
        var fullFileName = path.join(local_repos, param.fileName);
        // var emitter = new events.EventEmitter();
        fs.exists(fullFileName, function (exists) {
            if (exists) {
                fs.lstat(param.tar_fullPath, function (err, stat) {
                    if (stat.isDirectory()) {
                        param.tar_fullPath = path.join(param.tar_fullPath, param.fileName);
                    }
                    var readStream = fs.createReadStream(fullFileName);
                    var writeStream = fs.createWriteStream(param.tar_fullPath);
                    writeStream.on('err', function (err, data) {
                        readStream.pause();
                        exe_callback(err, data, callback);
                    });
                    readStream.on('err', function (err, data) {
                        readStream.pause();
                        exe_callback(err, data, callback);
                    });
                    readStream.pipe(writeStream).on('finish', function () {
                        exe_callback(null, null, callback);
                    });
                });
            } else {
                exe_callback("文件" + fullFileName + "不存在,拷贝失败", null, callback);
            }
        });
    }
};
function exe_callback(err, data, callback) {
    if (callback && typeof callback === 'function') {
        callback(err, data);
    }
}
